package notice

import (
	"fmt"
	"time"
	"yunj/pkg/global"
	"yunj/pkg/yunj/app/controller/admin"
	"yunj/pkg/yunj/app/dto"
	"yunj/pkg/yunj/app/enum/admin/authenum"
	"yunj/pkg/yunj/app/enum/admin/noticeenum"
	"yunj/pkg/yunj/app/enum/admin/taskenum"
	"yunj/pkg/yunj/app/model"
	"yunj/pkg/yunj/core/response"
	"yunj/pkg/yunj/util"

	"github.com/gin-gonic/gin"
)

// 通知管理
type Notice struct {
	admin.Controller
}

// 顶部通知数据
func (ctrl *Notice) TopData(ctx *gin.Context) {
	res := dto.AdminNoticeTopNoticeResponse{}
	types := noticeenum.TypeEnum.GetSortConsts()
	for _, v := range types {
		typeRes, err := ctrl.getUnreadListResponse(&dto.AdminNoticeUnreadListData{Type: v, Page: 1})
		if err != nil {
			response.Fail(ctx, err.Error())
			return
		}
		res.TypeList = append(res.TypeList, typeRes)
	}
	response.Success(ctx, res)
}

// 顶部未读消息数据
func (ctrl *Notice) GetUnreadList(ctx *gin.Context) {
	// 获取数据
	var data dto.AdminNoticeUnreadListData
	ctx.ShouldBindJSON(&data)
	// 验证数据
	data.InitValidator(&data)
	if err := data.Check(); err != nil {
		response.Fail(ctx, err.Error())
		return
	}
	// 获取数据
	typeRes, err := ctrl.getUnreadListResponse(&data)
	if err != nil {
		response.Fail(ctx, err.Error())
		return
	}
	// 响应输出
	response.Success(ctx, typeRes)
}

// 获取顶部未读消息数据
func (ctrl *Notice) getUnreadListResponse(data *dto.AdminNoticeUnreadListData) (res *dto.AdminNoticeUnreadListResponse, err error) {
	res = &dto.AdminNoticeUnreadListResponse{
		Type:     data.Type,
		TypeDesc: noticeenum.TypeByValue(data.Type).GetDesc(),
		Items:    []*dto.AdminNoticeUnreadListItem{},
		PageSize: 10,
	}
	// 获取数量
	if data.Page == 1 {
		dbErr := global.MySQL.Model(&model.AdminNotice{}).Where("type = ? and read_at is null", data.Type).Count(&res.Count).Error
		if dbErr != nil {
			global.Logger.Error(util.FormatError(dbErr, "获取未读通知数量错误！"))
			err = fmt.Errorf("获取未读通知数量错误！")
			return
		}
	}
	// 获取数据
	var notices []*model.AdminNotice
	dbErr := global.MySQL.Where("type = ? and read_at is null", data.Type).Order("id desc").Limit(10).Offset(int(data.Page-1) * int(res.PageSize)).Find(&notices).Error
	if dbErr != nil {
		global.Logger.Error(util.FormatError(dbErr, "获取未读通知数据错误！"))
		err = fmt.Errorf("获取未读通知数据错误！")
		return
	}
	for _, notice := range notices {
		noticeId, _ := util.ToString(notice.Id)
		res.Items = append(res.Items, &dto.AdminNoticeUnreadListItem{
			DataId:    notice.DataId,
			CreatedAt: notice.CreatedAt.Format("2006-01-02 15:04:05"),
			Desc:      notice.Desc,
			Type:      notice.Type,
			Id:        noticeId,
		})
	}
	// 获取通知对象数据
	if data.Type == noticeenum.TYPE_TASK {
		// 任务
		// 查看更多
		res.ViewMoreUrl = util.BuildAdminUrl("/task/list", map[string]any{"originLocation": authenum.TYPE_SIDEBAR_MENU})
		res.ViewMoreTitle = "任务管理"
		taskIds := []uint64{}
		taskIdResItemIdx := map[uint64]int{}
		for i, item := range res.Items {
			var taskId uint64
			taskId, err = util.ToUint64(item.DataId)
			if err != nil {
				global.Logger.Error(util.FormatError(err, "任务类型通知id转换异常！"))
				err = fmt.Errorf("任务类型通知id转换异常！")
				return
			}
			taskIds = append(taskIds, taskId)
			taskIdResItemIdx[taskId] = i
		}
		if len(taskIds) > 0 {
			var tasks []*model.AdminTask
			dbErr := global.MySQL.Where("id in ?", taskIds).Find(&tasks).Error
			if dbErr != nil {
				err = fmt.Errorf("获取任务类型通知的数据对象失败！%v", dbErr)
				return
			}
			for _, task := range tasks {
				taskId := task.Id
				noticeIcon := taskenum.TypeByValue(task.Type).GetNoticeIcon()
				if idx, exists := taskIdResItemIdx[taskId]; exists {
					res.Items[idx].Icon = noticeIcon
					res.Items[idx].ViewUrl = fmt.Sprintf("%s&task_ids=%d", res.ViewMoreUrl, taskId)
					res.Items[idx].ViewTitle = "任务管理"
				}
			}
		}
	}
	return
}

// 已读处理
func (ctrl *Notice) Read(ctx *gin.Context) {
	// 获取数据
	var data dto.AdminNoticeReadData
	ctx.ShouldBindJSON(&data)
	// 验证数据
	data.InitValidator(&data)
	if err := data.Check(); err != nil {
		response.Fail(ctx, err.Error())
		return
	}
	// 处理已读
	ids := make([]uint64, 0, len(data.Ids))
	for _, id := range data.Ids {
		idUint64, err := util.ToUint64(id)
		if err != nil {
			response.Fail(ctx, "请求数据异常！")
			return
		}
		ids = append(ids, idUint64)
	}
	handleQuery := global.MySQL.Model(&model.AdminNotice{}).Where("type = ? and read_at is null", data.Type)
	if len(ids) > 0 {
		handleQuery.Where("id in ?", ids)
	}
	currTime := time.Now().In(time.Local)
	dbErr := handleQuery.Update("read_at", currTime).Error
	// 响应
	if dbErr != nil {
		global.Logger.Error(util.FormatError(dbErr, "通知已读处理异常！"))
		response.Fail(ctx, "通知已读处理异常！")
		return
	}
	response.Success(ctx, nil)
}
